﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using BEX.Core;
using BEX.Core.Exchange;

namespace BEX.DataAccess
{
    public class TickDAL
    {


        public static bool Save(Tick toSave)
        {
            var res = true;

            var _context = new BTCDataClassesDataContext();

            var _tick = (from c in _context.GetTable<EXCHANGE_TICK>()
                         where c.ID == toSave.Id
                         select c).SingleOrDefault();

            if (null == _tick)
            {
                var _acc = GetTickTable();

                var _t = new EXCHANGE_TICK();

                _t.ASK = toSave.Ask;
                _t.BID = toSave.Bid;
                _t.BASE_CURRENCY_ID = (int)toSave.Currency.Base;
                _t.COUNTER_CURRENCY_ID = (int)toSave.Currency.Counter;
                _t.EXCHANGE_ID = (int)toSave.ExchangeSource;
                _t.UTC_TIME = toSave.Time;
                _t.SPOT = toSave.Spot;

                _acc.InsertOnSubmit(_t);
                _acc.Context.SubmitChanges();
            }
            else
            {
                _tick.ASK = toSave.Ask;
                _tick.BID = toSave.Bid;
                _tick.BASE_CURRENCY_ID = (int)toSave.Currency.Base;
                _tick.COUNTER_CURRENCY_ID = (int)toSave.Currency.Counter;
                _tick.EXCHANGE_ID = (int)toSave.ExchangeSource;
                _tick.UTC_TIME = toSave.Time;
                _tick.SPOT = toSave.Spot;

                _context.SubmitChanges();
            }


            return res;
        }

        public static System.Data.Linq.Table<EXCHANGE_TICK> GetTickTable()
        {
            var _context = new BTCDataClassesDataContext();

            return _context.GetTable<EXCHANGE_TICK>();
        }

        public static List<Tick> GetList()
        {
            var res = new List<Tick>();

            var _l = ExchangeTickList();

            foreach (EXCHANGE_TICK _a in _l)
            {
                var _toAdd = new Tick();

                CurrencyPair pair = new CurrencyPair();
                pair.Base = (CurrencyType)_a.BASE_CURRENCY_ID;
                pair.Counter = (CurrencyType)_a.COUNTER_CURRENCY_ID;

                _toAdd.Ask = _a.ASK;
                _toAdd.Currency = pair;
                _toAdd.Bid = _a.BID;
                _toAdd.ExchangeSource = (ExchangeType)_a.EXCHANGE_ID;
                _toAdd.Id = _a.ID;
                _toAdd.Time = _a.UTC_TIME;
                _toAdd.Spot = _a.SPOT;


                res.Add(_toAdd);
            }

            return res;
        }

        private static List<EXCHANGE_TICK> ExchangeTickList()
        {
            var _context = new BTCDataClassesDataContext();


            return (from acc in _context.GetTable<EXCHANGE_TICK>()
                    select acc).ToList<EXCHANGE_TICK>();
        }

        public static Tick GetCurrentTick(ExchangeType _source, CurrencyPair pair)
        {
            var _context = new BTCDataClassesDataContext();

            var _e = (from acc in _context.GetTable<EXCHANGE_TICK>()
                      where (acc.BASE_CURRENCY_ID == (int)pair.Base && acc.COUNTER_CURRENCY_ID == (int)pair.Counter && acc.EXCHANGE_ID == (int)_source)
                      orderby acc.UTC_TIME descending
                      select acc).Take(1);


            EXCHANGE_TICK _t = null;

            if (null != _e && _e.ToList().Count > 0)
            {
                _t = _e.Single();
            }


            if (null != _t && (_t.ASK > 0 || _t.SPOT > 0))
            {
                var _toAdd = new Tick();



                _toAdd.Ask = _t.ASK;
                _toAdd.Currency = pair;
                _toAdd.Bid = _t.BID;
                _toAdd.ExchangeSource = (ExchangeType)_t.EXCHANGE_ID;
                _toAdd.Id = _t.ID;
                _toAdd.Time = _t.UTC_TIME;
                _toAdd.Spot = _t.SPOT;

                return _toAdd;
            }
            else
            {
                return null;
            }
        }

        public static Tick GetCurrentSpot(ExchangeType _source, CurrencyPair pair)
        {
            var _context = new BTCDataClassesDataContext();

            var _e = (from acc in _context.GetTable<EXCHANGE_TICK>()
                      where (acc.BASE_CURRENCY_ID == (int)pair.Base && acc.COUNTER_CURRENCY_ID == (int)pair.Counter && acc.EXCHANGE_ID == (int)_source)
                      orderby acc.UTC_TIME descending
                      select acc).Take(1);

            EXCHANGE_TICK _t = null;

            if (null != _e && _e.ToList().Count > 0)
            {
                _t = _e.Single();
            }
            if (null != _t && (null != _t.SPOT && _t.SPOT > 0))
            {
                var _toAdd = new Tick();

                _toAdd.Ask = _t.ASK;
                _toAdd.Currency = pair;
                _toAdd.Bid = _t.BID;
                _toAdd.ExchangeSource = (ExchangeType)_t.EXCHANGE_ID;
                _toAdd.Id = _t.ID;
                _toAdd.Time = _t.UTC_TIME;
                _toAdd.Spot = _t.SPOT;

                return _toAdd;
            }
            else
            {
                return null;
            }
        }

        public static Tick GetTickByID(int ID)
        {
            var _context = new BTCDataClassesDataContext();

            var _e = (from acc in _context.GetTable<EXCHANGE_TICK>()
                      where (acc.ID == ID)
                      select acc).Take(1);


            EXCHANGE_TICK _t = null;

            if (null != _e && _e.ToList().Count > 0)
            {
                _t = _e.Single();
            }
            if (null != _t && (_t.ASK > 0 || _t.SPOT > 0))
            {
                var _toAdd = new Tick();

                CurrencyPair pair = new CurrencyPair();
                pair.Base = (CurrencyType)_t.BASE_CURRENCY_ID;
                pair.Counter = (CurrencyType)_t.COUNTER_CURRENCY_ID;

                _toAdd.Ask = _t.ASK;
                _toAdd.Currency = pair;
                _toAdd.Bid = _t.BID;
                _toAdd.ExchangeSource = (ExchangeType)_t.EXCHANGE_ID;
                _toAdd.Id = _t.ID;
                _toAdd.Time = _t.UTC_TIME;
                _toAdd.Spot = _t.SPOT;

                return _toAdd;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// Return the tick that immediately precedes the supplied tick
        /// </summary>
        /// <returns>Tick</returns>
        public static Tick GetPreviousTick(ExchangeType _source, Tick current)
        {
            var _context = new BTCDataClassesDataContext();

            var _e = (from acc in _context.GetTable<EXCHANGE_TICK>()
                      where (acc.BASE_CURRENCY_ID == (int)current.Currency.Base
                                                            && acc.COUNTER_CURRENCY_ID == (int)current.Currency.Counter
                                                            && acc.EXCHANGE_ID == (int)_source
                                                            && acc.ID < current.Id)
                      orderby acc.ID descending
                      select acc).Take(1);

            EXCHANGE_TICK res = null;

            if (_e.ToList().Count > 0)
            {
                res = _e.Single<EXCHANGE_TICK>();
            }
            if (null != res && (res.ASK > 0 || res.SPOT > 0))
            {
                var _toAdd = new Tick();

                _toAdd.Ask = res.ASK;
                _toAdd.Currency = current.Currency;
                _toAdd.Bid = res.BID;
                _toAdd.ExchangeSource = (ExchangeType)res.EXCHANGE_ID;
                _toAdd.Id = res.ID;
                _toAdd.Time = res.UTC_TIME;
                _toAdd.Spot = res.SPOT;

                return _toAdd;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// Return the tick that immediately follows the supplied tick
        /// </summary>
        /// <returns>Tick</returns>
        public static Tick GetNextConsecutiveTick(ExchangeType _source, Tick current)
        {
            var _context = new BTCDataClassesDataContext();

            var _e = (from acc in _context.GetTable<EXCHANGE_TICK>()
                      where (acc.BASE_CURRENCY_ID == (int)current.Currency.Base
                                                            && acc.COUNTER_CURRENCY_ID == (int)current.Currency.Counter
                                                            && acc.EXCHANGE_ID == (int)_source
                                                            && acc.ID > current.Id)
                      orderby acc.ID
                      select acc).Take(1);

            EXCHANGE_TICK res = null;

            if (_e.ToList().Count > 0)
            {
                res = _e.Single();
            }
            if (null != res && (res.ASK > 0 || res.SPOT > 0))
            {
                var _toAdd = new Tick();

                _toAdd.Ask = res.ASK;
                _toAdd.Currency = current.Currency;
                _toAdd.Bid = res.BID;
                _toAdd.ExchangeSource = (ExchangeType)res.EXCHANGE_ID;
                _toAdd.Id = res.ID;
                _toAdd.Time = res.UTC_TIME;
                _toAdd.Spot = res.SPOT;

                return _toAdd;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// Return the tick that immediately precedes the supplied tick
        /// </summary>
        /// <returns>Tick</returns>
        public static int? GetMaximumSpot(ExchangeType _source, Tick current, int timespan)
        {
            var _context = new BTCDataClassesDataContext();

            DateTime _oldLimit;

            _oldLimit = current.Time.AddSeconds(-timespan);

            var max = 0;
            try
            {
                max = (from acc in _context.GetTable<EXCHANGE_TICK>()
                       where (acc.BASE_CURRENCY_ID == (int)current.Currency.Base
                             && acc.COUNTER_CURRENCY_ID == (int)current.Currency.Counter
                             && acc.EXCHANGE_ID == (int)_source
                             && acc.UTC_TIME > _oldLimit
                             )
                       select acc.SPOT).Max();
            }
            catch (Exception ex)
            {
                return null;
            }

            return max;
        }


        /// <summary>
        /// Return the tick that immediately precedes the supplied tick
        /// </summary>
        /// <returns>Tick</returns>
        public static int? GetMinSpot(ExchangeType _source, Tick current, int timespan)
        {
            var _context = new BTCDataClassesDataContext();

            DateTime _oldLimit;

            _oldLimit = current.Time.AddSeconds(-timespan);

            var min = 0;
            try
            {
                min = (from acc in _context.GetTable<EXCHANGE_TICK>()
                       where (acc.BASE_CURRENCY_ID == (int)current.Currency.Base
                             && acc.COUNTER_CURRENCY_ID == (int)current.Currency.Counter
                             && acc.EXCHANGE_ID == (int)_source
                             && acc.UTC_TIME > _oldLimit
                             )
                       select acc.SPOT).Min();
            }
            catch (Exception ex)
            {
                return null;
            }

            return min;
        }
    }
}
